// MFunction.cpp : Implementation of CMudosApp and DLL registration.

#include "stdafx.h"
#include "m.h"

/////////////////////////////////////////////////////////////////////////////
//

STDMETHODIMP CMFunction::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* arr[] = 
	{
		&IID_IMFunction,
	};

	for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
	{
		if (InlineIsEqualGUID(*arr[i],riid))
			return S_OK;
	}
	return S_FALSE;
}

STDMETHODIMP CMFunction::get_Name(BSTR * pVal)
{
	// TODO: Add your implementation code here
	if(!pVal)return S_FALSE;
	Cc2w c2w;
	program_t *p;
	p=ob->GetProg();
	c2w.in(p->function_table[m_id].name);
	*pVal=SysAllocString(c2w.out());
	return S_OK;
}

STDMETHODIMP CMFunction::get_ParamCount(int * pVal)
{
	// TODO: Add your implementation code here
	if(!pVal)return S_FALSE;
	program_t *p;
	int index;
	p=ob->GetProg();
	index=p->function_table[m_id].runtime_index;
	*pVal=p->function_offsets[index].def.num_arg;
	return S_OK;
}

STDMETHODIMP CMFunction::AddParam(IMValue * pVal)
{
	// TODO: Add your implementation code here
	if(!pVal)return S_FALSE;
	if(index>=16)return S_FALSE;
	pVal->QueryInterface(IID_IMValue,(void **)&param[index]);
	index++;
	return S_OK;
}

STDMETHODIMP CMFunction::ClearParam()
{
	// TODO: Add your implementation code here
	int i;
	for(i=0;i<index;i++){
		param[i]->Release();
	}
	index=0;
	return S_OK;
}

STDMETHODIMP CMFunction::get_Ret(IMValue * * pVal)
{
	// TODO: Add your implementation code here
	if(!pVal)return S_FALSE;
	if(!ret)return S_FALSE;
	ret->AddRef();
	*pVal=ret;
	return S_OK;
}

extern "C" void call_function_with_param (object_t *ob,char *funcname,svalue_t *param,int paramcount,svalue_t *ret);

STDMETHODIMP CMFunction::Apply()
{
	// TODO: Add your implementation code here
	program_t *p;
	int i,idx;
	svalue_t sparam[16];
	svalue_t sret;

	for(i=0;i<index;i++){
		sparam[i]=*(param[i]->GetSValue());
	}
	p=ob->GetProg();
	idx=p->function_table[m_id].runtime_index;
	if(index!=p->function_offsets[idx].def.num_arg)return S_FALSE;
	call_function_with_param(ob->GetOb(),p->function_table[m_id].name,
		sparam,index,&sret);
	if(ret)ret->Release();
	ret=new CComObject<CMValue>;
	ret->Create(&sret);
	ret->AddRef();
	_free_svalue(&sret,"IMFunction::Apply");
	return S_OK;
}
